﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO.Ports;

namespace comm_num_tp1
{
    public partial class MainWindow : Form
    {
        #region private variables
        private GpsAcquireStream _gpsToDevice = new GpsAcquireStream();
        private Control[, ,] _gsvControl = new Control[3, 4, 6];
        #endregion
        delegate void AddAllGpsStream(object sender, GpsStreamEventArgs gpsE);

        #region constructor
        public MainWindow()
        {
            InitializeComponent();
            SetInitialWindowComponent();
            SetGsvControl();
        }

        private void SetGsvControl()
        {
            // Gsv1 Sat 1
            _gsvControl[0, 0, 0] = grpbGsv1Sat1;
            _gsvControl[0, 0, 1] = lblGsv1Sat1Elevation;
            _gsvControl[0, 0, 2] = lblGsv1Sat1Azimuth;
            _gsvControl[0, 0, 3] = lblGsv1Sat1Noise;
            _gsvControl[0, 0, 4] = txtGsv1StreamAll;
            _gsvControl[0, 0, 5] = gpGsv1SignalAverage;
            // Gsv1 Sat 2
            _gsvControl[0, 1, 0] = grpbGsv1Sat2;
            _gsvControl[0, 1, 1] = lblGsv1Sat2Elevation;
            _gsvControl[0, 1, 2] = lblGsv1Sat2Azimuth;
            _gsvControl[0, 1, 3] = lblGsv1Sat2Noise;
            _gsvControl[0, 1, 5] = gpGsv1SignalAverage;
            // Gsv1 Sat 3
            _gsvControl[0, 2, 0] = grpbGsv1Sat3;
            _gsvControl[0, 2, 1] = lblGsv1Sat3Elevation;
            _gsvControl[0, 2, 2] = lblGsv1Sat3Azimuth;
            _gsvControl[0, 2, 3] = lblGsv1Sat3Noise;
            _gsvControl[0, 2, 5] = gpGsv1SignalAverage;
            // Gsv1 Sat 4
            _gsvControl[0, 3, 0] = grpbGsv1Sat4;
            _gsvControl[0, 3, 1] = lblGsv1Sat4Elevation;
            _gsvControl[0, 3, 2] = lblGsv1Sat4Azimuth;
            _gsvControl[0, 3, 3] = lblGsv1Sat4Noise;
            _gsvControl[0, 3, 5] = gpGsv1SignalAverage;

            // Next Gsv Stream
            // Gsv2 Sat 1
            _gsvControl[1, 0, 0] = grpbGsv2Sat1;
            _gsvControl[1, 0, 1] = lblGsv2Sat1Elevation;
            _gsvControl[1, 0, 2] = lblGsv2Sat1Azimuth;
            _gsvControl[1, 0, 3] = lblGsv2Sat1Noise;
            _gsvControl[1, 0, 4] = txtGsv2StreamAll;
            _gsvControl[1, 0, 5] = gpGsv2SignalAverage;
            // Gsv2 Sat 2
            _gsvControl[1, 1, 0] = grpbGsv2Sat2;
            _gsvControl[1, 1, 1] = lblGsv2Sat2Elevation;
            _gsvControl[1, 1, 2] = lblGsv2Sat2Azimuth;
            _gsvControl[1, 1, 3] = lblGsv2Sat2Noise;
            _gsvControl[1, 1, 5] = gpGsv2SignalAverage;
            // Gsv2 Sat 3
            _gsvControl[1, 2, 0] = grpbGsv2Sat3;
            _gsvControl[1, 2, 1] = lblGsv2Sat3Elevation;
            _gsvControl[1, 2, 2] = lblGsv2Sat3Azimuth;
            _gsvControl[1, 2, 3] = lblGsv2Sat3Noise;
            _gsvControl[1, 2, 5] = gpGsv2SignalAverage;
            // Gsv2 Sat 4
            _gsvControl[1, 3, 0] = grpbGsv2Sat4;
            _gsvControl[1, 3, 1] = lblGsv2Sat4Elevation;
            _gsvControl[1, 3, 2] = lblGsv2Sat4Azimuth;
            _gsvControl[1, 3, 3] = lblGsv2Sat4Noise;
            _gsvControl[1, 3, 5] = gpGsv2SignalAverage;

            // Next Gsv Stream
            // Gsv3 Sat 1
            _gsvControl[2, 0, 0] = grpbGsv3Sat1;
            _gsvControl[2, 0, 1] = lblGsv3Sat1Elevation;
            _gsvControl[2, 0, 2] = lblGsv3Sat1Azimuth;
            _gsvControl[2, 0, 3] = lblGsv3Sat1Noise;
            _gsvControl[2, 0, 4] = txtGsv3StreamAll;
            _gsvControl[2, 0, 5] = gpGsv3SignalAverage;
            // Gsv3 Sat 2
            _gsvControl[2, 1, 0] = grpbGsv3Sat2;
            _gsvControl[2, 1, 1] = lblGsv3Sat2Elevation;
            _gsvControl[2, 1, 2] = lblGsv3Sat2Azimuth;
            _gsvControl[2, 1, 3] = lblGsv3Sat2Noise;
            _gsvControl[2, 1, 5] = gpGsv3SignalAverage;
            // Gsv3 Sat 3
            _gsvControl[2, 2, 0] = grpbGsv3Sat3;
            _gsvControl[2, 2, 1] = lblGsv3Sat3Elevation;
            _gsvControl[2, 2, 2] = lblGsv3Sat3Azimuth;
            _gsvControl[2, 2, 3] = lblGsv3Sat3Noise;
            _gsvControl[2, 2, 5] = gpGsv3SignalAverage;
            // Gsv3 Sat 1
            _gsvControl[2, 3, 0] = grpbGsv3Sat4;
            _gsvControl[2, 3, 1] = lblGsv3Sat4Elevation;
            _gsvControl[2, 3, 2] = lblGsv3Sat4Azimuth;
            _gsvControl[2, 3, 3] = lblGsv3Sat4Noise;
            _gsvControl[2, 3, 5] = gpGsv3SignalAverage;
        }
        #endregion

        #region receive Complete Stream
        /// <summary>
        /// Display a GGA stream on mainwindow
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="gpsE"></param>
        void DisplayGGA(object sender, GpsStreamEventArgs gpsE)
        {

        }

        /// <summary>
        /// Display a RMC stream on mainwindow
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="gpsE"></param>
        void DisplayRMC(object sender, GpsStreamEventArgs gpsE)
        {

        }

        /// <summary>
        /// Display a GSV stream on mainwindow
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="gpsE"></param>
        void DisplayGSV(object sender, GpsStreamEventArgs gpsE)
        {

        }
        #endregion

        /// <summary>
        /// Set component on main window.
        /// </summary>
        private void SetInitialWindowComponent()
        {
            string[] currentPort = SerialPort.GetPortNames();
            if (currentPort != null)
            {
                for (int i = 0; i < currentPort.Length; i++)
                    cmbPortName.Items.Add(currentPort[i]);
                cmbPortName.Refresh();
            }

        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            _gpsToDevice.GpGgaEvent += new GpsAcquireStream.GpsEventHandler(this.GpsStreamGga);
            _gpsToDevice.GpRmcEvent += new GpsAcquireStream.GpsEventHandler(this.GpsStreamRmc);
            _gpsToDevice.GpGsvEvent += new GpsAcquireStream.GpsEventHandler(this.GpsStreamGsvList);
            _gpsToDevice.baudRate = 4800;
            _gpsToDevice.dataBits = 8;
            _gpsToDevice.parity = System.IO.Ports.Parity.None;
            Thread GpsThreadStartReading = new Thread(_gpsToDevice.GpsStreamStart);
            if (cmbPortName.SelectedIndex != -1)
            {
                _gpsToDevice.comName = cmbPortName.Items[cmbPortName.SelectedIndex].ToString();
                if (_gpsToDevice.GpsConnect())
                {
                    GpsThreadStartReading.Start();
                }
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            _gpsToDevice.GpsStreamStop();
            _gpsToDevice.GpsDisconnect();
            _gpsToDevice = new GpsAcquireStream();
            ResetAllGsvControl();
            ResetAllGenPurposeControl();
        }

        /// <summary>
        /// Add this GpsStream to the listBox where all these are displayed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="gpsE"></param>
        private void GpsStreamNewStream(string rawStream)
        {
            
            lstGpsStream.Items.Add(rawStream);
            if (lstGpsStream.Items.Count > 50)
                lstGpsStream.Items.RemoveAt(0);
        }

        /// <summary>
        /// Display Gga stream in its own place in the main Window
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="gpsE"></param>
        private void GpsStreamGga(object sender, GpsStreamEventArgs gpsE)
        {
            if (txtGgaAllStream.InvokeRequired)
            {
                AddAllGpsStream AddAllGpsDelegate = new AddAllGpsStream(GpsStreamGga);
                txtGgaAllStream.Invoke(AddAllGpsDelegate, new object[] { sender, gpsE });
            }
            else
            {
                GpGGA tempStream = (GpGGA)gpsE.GetStream;
                txtGgaAllStream.Text = tempStream.ToString();
                txtGgaLat.Text = tempStream.StreamLat;
                txtGgaLon.Text = tempStream.StreamLon;
                lblGgaQty.Text = tempStream.StreamSatQty;
                GpsStreamNewStream(tempStream.StreamRawStream);
            }
        }

        /// <summary>
        /// Display Rmc stream in its own place in the main Window
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="gpsE"></param>
        private void GpsStreamRmc(object sender, GpsStreamEventArgs gpsE)
        {
            if (txtRmcAllStream.InvokeRequired)
            {
                AddAllGpsStream AddAllGpsDelegate = new AddAllGpsStream(GpsStreamRmc);
                txtRmcAllStream.Invoke(AddAllGpsDelegate, new object[] { sender, gpsE });
            }
            else
            {
                GpRMC tempStream = (GpRMC)gpsE.GetStream;
                txtRmcAllStream.Text = tempStream.ToString();
                lblRmcTime.Text = tempStream.StreamCoolTime;
                lblRmcMagnetVar.Text = tempStream.StreamDeclMagnetDeg;
                lblRmcMagnetVarDirection.Text = tempStream.StreamBearing;
                GpsStreamNewStream(tempStream.StreamRawStream);
            }
        }

        /// <summary>
        /// Print Gsv Stream value on MainWindow
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="gpsE"></param>
        private void GpsStreamGsvList(object sender, GpsStreamEventArgs gpsE)
        {
            if (grpbGsv1.InvokeRequired)
            {
                AddAllGpsStream AddAllGpsDelegate = new AddAllGpsStream(GpsStreamGsvList);
                grpbGsv1.Invoke(AddAllGpsDelegate, new object[] { sender, gpsE });
            }
            else
            {
                //ResetAllGsvControl();
                GpGSVList myGsvList = (GpGSVList)gpsE.GetStream;
                int totalSat = 0;
                int signalNoise;
                // Total Sat Overview
                foreach (GpGSV gsv in myGsvList)
                    totalSat += gsv.SateliteList.Count;
                lblGsvTotalSat.Text = totalSat.ToString();

                for (int gsvstream = 0; gsvstream < myGsvList.Count; gsvstream++)
                {
                    signalNoise = 0;
                    ((TextBox)_gsvControl[gsvstream, 0, 4]).Text = myGsvList[gsvstream].ToString();
                    GpsStreamNewStream(((TextBox)_gsvControl[gsvstream, 0, 4]).Text);
                    for (int satelite = 0; satelite < myGsvList[gsvstream].SateliteList.Count; satelite++)
                    {
                        int tempSignalNoise = 0;
                        ((GroupBox)_gsvControl[gsvstream, satelite, 0]).Text = "Satelite (PRN #" +
                            myGsvList[gsvstream].SateliteList[satelite].StreamSatIden + ")";
                        ((Label)_gsvControl[gsvstream, satelite, 1]).Text = myGsvList[gsvstream].SateliteList[satelite].StreamElevDegSat;
                        ((Label)_gsvControl[gsvstream, satelite, 2]).Text = myGsvList[gsvstream].SateliteList[satelite].StreamAzimuthSat;
                        ((Label)_gsvControl[gsvstream, satelite, 3]).Text = myGsvList[gsvstream].SateliteList[satelite].StreamSignalStrength;
                        Int32.TryParse(((Label)_gsvControl[gsvstream, satelite, 3]).Text, out tempSignalNoise);
                        signalNoise += tempSignalNoise;
                        tempSignalNoise = signalNoise / (satelite + 1);
                        if (satelite + 1 == myGsvList[gsvstream].SateliteList.Count)
                            ((Label)_gsvControl[gsvstream, satelite, 5]).Text = tempSignalNoise.ToString();
                    }
                }
            }
        }

        /// <summary>
        /// Reset Form control Label and TextBox to intial value
        /// </summary>
        private void ResetAllGsvControl()
        {
            foreach (Control grp in splitContainer1.Panel2.Controls)
            {
                foreach (Control c in grp.Controls)
                {
                    if (c is TextBox)
                        c.Text = "";
                    if (c is GroupBox && (string)((GroupBox)c).Tag != "MainGsv")
                        ((GroupBox)c).Text = "Satelite (PRN Number)";
                    foreach (Control y in c.Controls)
                    {
                        if (y is TextBox)
                            ((TextBox)y).Text = "";
                        else if (y is Label && (string)y.Tag == "value")
                            ((Label)y).Text = "-";
                    }
                }
            }
            gpGsv1SignalAverage.Text = gpGsv2SignalAverage.Text = gpGsv3SignalAverage.Text = "-";
        }

        private void ResetAllGenPurposeControl()
        {
            foreach (Control grp in splitContainer1.Panel1.Controls)
            {
                foreach (Control c in grp.Controls)
                {
                    if (c is TextBox)
                        ((TextBox)c).Text = "";
                    else if (c is Label && (string)c.Tag == "value")
                        ((Label)c).Text = "-";
                }
            }
            lstGpsStream.Items.Clear();
        }
    }
}
